package com.mycompany.project.client;

import com.bramosystems.oss.player.core.client.AbstractMediaPlayer;
import com.bramosystems.oss.player.core.client.LoadException;
import com.bramosystems.oss.player.core.client.PlayException;
import com.bramosystems.oss.player.core.client.PluginNotFoundException;
import com.bramosystems.oss.player.core.client.RepeatMode;
import com.bramosystems.oss.player.core.client.ui.NativePlayer;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.dom.client.MouseWheelEvent;
import com.google.gwt.event.dom.client.MouseWheelHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.smartgwt.client.types.AnimationEffect;
import com.smartgwt.client.types.BkgndRepeat;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.widgets.Slider;
import com.smartgwt.client.widgets.events.ValueChangedHandler;
import com.smartgwt.client.widgets.events.ValueChangedEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.user.client.ui.TextBox;
import com.smartgwt.client.widgets.Canvas;



/**
 * @author Laboratorio Tv Collaborativa/Contenuti Digitali --> Sardegna District --> Crs4 --> Sardegna Ricerche
 * 
 * Entry point classes that define the method <code>onModuleLoad()</code> and it is the main class of @SaStria annotation tool. 
 * The goal of this class is manage and initialize the graphic user interface of web application. Other tasks of this class
 * are the management of SaStria annotation tool and coordination of SaStria object and elements.
 */
public class SaStriaApp implements EntryPoint {
	
	// Media player object that deals of manage the video. 
	private AbstractMediaPlayer mediaPlayer;
	
	// button play/pause of video controls. It is situated in the VideoControls panel.
	private ToggleButton buttonPlayPause;
	
	// button volume of video player. It is situated in the VideoControls panel.
	private ToggleButton buttonVolume;
	
	// Time size of video in ms
	private double durataVideo;
	
	// Text to show on progress bar when the video is in play
	private String testoPlayerPlay;
	
	// Text to show on progress bar when the video is in pause
	private String testoPlayerPause;
	
	// Timer object used for the Synchronization of video play position with the progress bar percentage progress
	private Timer timerProgressBar;
	
	// Preogress bar that show the video play position progress.
	private MyProgressBar progressBarVideo;
	
	// Timer object used for the Synchronization of video play position with the progress bar percentage 
	// progress when a pause event occurs.   
	private Timer timerVideoPauseTimeOut;
	
	// Time of resfresh in milliseconds(ms) of ProgressBar progress. Indicates the time between two consecutive steps 
	// of progress bar update.
	private final int timerRefreshScroolbar=100;
	
	// Indicates the Time to wait for update ProgressBar progress after a pause event occurs 
	private final int timeTimeOutPause=1000;
	
	// Indicates the time in ms to wait before close the volume box slider container if no action runs on volume slider.
	private final int timeTimeOutCloseSlideBar=1500;
	
	// constant used for represent 500 ms
	private final int timeCinquecentoMs=500;
	
	//offset timer in ms used to add at timerRefreshScroolbar in special cases as back and forward video
	private final int timerRefreshScroolbarOffsetRealignment=100;
	
	// offset used for the fast scrool of video after a mouse whell scrool on it. For example, if mouse wheel make a two rotation steps on
	// video it must be advanced of two steps. To have a visible movement is necessary use this offset value multiplied foe mouse wheel steps.
	// In this example the video is advanced by 2*offsetBackForward frame.
	private final int offsetBackForward=80;
	
	// This boolean variable represents the status of Button End in video controls. True if button is pressed false otherwise.
	private boolean bEndPressed;
	
	//This boolean variable represents the status of volume slider in video controls. True if volume slider is visible false otherwise.
	private boolean sliderVolumeFocused;
	
	// Value of current video volume
	private double valoreVolume;
	
	// Main panel container of @SaStria application. It represent the browser web page where to draw the application components.  
	private AbsolutePanel canvasPagina;
	
	// Slider for video volume settings
	private Slider sliderVolume;
	
	// costant value used for setting the volume slider height  
	private final int sliderVolumeHeight=90;
	
	// Url of the current video in play on @SaStria annotation tool
	private String videoInPlay;
	
	// PopUp window used for open the video in full screen mode 
	private PlayerFullScreen fullScreen;
	
	// Boolean variable used for controlling and manage the drag on Progress Bar video cursor. If true means that
	// the users are doing a drag on video cursor on progress bar changing the video play position, false otherwise.
	private boolean dragPBarStart;
	
	/*
	 * This boolean variable is used to control the status of video play before that the user triggers an event on video. 
	 * If true means that the video was in play before the user trigger an event on video as change the video play position
	 * by progress bar. This is used for put the video player in the same status it had before the user trigger an event. 
	 * 
	 * */	
	private boolean videoWasInPlay;
	
	// boolean value where if true means that the mouse move over the progress bar, false otherwise.	
	private boolean mouseIsOverPBar;
	
	// boolean value where if true means that the play position of video can be changed manually by the user. false otherwise.
	private boolean videoCanBackForward;
	
	// Panel container of video player. This is the container of html5 tag "<video> </video>".
	private AbsolutePanel panelVideoContainer;
	
	// Panel container of annotation links. In this panel annotations links are sorted and arranged in time
	// as if it were a progress bar that displays also the links to annotations. it is called annotation Bar.
	private Canvas annotationBar;
	
	// This ScroolPanel is used for the scrolling of annotations within annotations bar. When in the annotation
	// bar more annotations overlap, If they can not be shown in the same Y area of the visible annotations, then 
	// is necessary to do a scroll for display all annotations.	
	private ScrollPanel scrollPanel;
	
	// Panel container of annotation bar e scroolPanel( for annotations scrolling).	
	private AbsolutePanel panelAnnotationBar;
	
	// This is a object used for manage the annotations such as the annotations tag on the video and 
	// annotations on the annotation bar 
	private AnnotationAdministrator annotations;
	
	// Annottaion preview panel container
	private AnnotationPreviewPanel annotationPrewPanel;
	
	private CloudTagLinks cloudTagLinksPanel;
	
	/**
	 * This method take as input an event of MouseWheelEvent and the its goals is calculate the number of
	 * mouse wheels rotations and accordingly calculate the new video play position. To calculate the new video
	 * play position we calculate the number of frames forward / backward. To have a significative and visible 
	 * video movement is necessary multiply the numbers of forward / backward frames for a offsetValue.      
	 * @param MouseWheelEvent event: mouse event from which to read the mouse wheels rotations step.
	 */
	private void mouseWhellOnVideo(MouseWheelEvent event){
		int offset;
		
		offset=event.getDeltaY();  // Get mouse wheel rotations step
		
		// The mouse wheel rotations step can be a negative value so is necessary extract the absolute value  
		offset=Math.abs(offset);
		
		/*
		 * The calculation of the new video play position is made in proportion mode to the number of rotation steps taken 
		 * by the mouse wheel. In this way a small mouse wheel movements correspond to a small video play position changes,
		 * while at most significative mouse wheel movements corresponds proportional video play position changes.	  
		 * */
		switch (offset) {
		case 1:offset=(offsetBackForward/2);
			   break;
		case 2:offset=(offsetBackForward);
			   break;
		case 3:offset=offsetBackForward*2;
			   break;
		case 4:offset=offsetBackForward *4;
			   break;
		case 5:offset=offsetBackForward*6;
			   break;
		case 6:offset=offsetBackForward*8;
			   break;
		case 7:offset=offsetBackForward*10;
			   break;
		case 8:offset=offsetBackForward*12;
			   break;
		case 9:offset=offsetBackForward*14;
			   break;
		case 10:offset=offsetBackForward*16;
			   break;
		case 11:offset=offsetBackForward*18;
			   break;
		case 12:offset=offsetBackForward*20;
			   break;
		case 13:offset=offsetBackForward*22;
			   break;
		case 14:offset=offsetBackForward*24;
			   break;
		case 15:offset=offsetBackForward*26;
			   break;
		case 16:offset=offsetBackForward*28;
			   break;
		case 17:offset=offsetBackForward*30;
		   break;
		case 18:offset=offsetBackForward*32;
		   break;
		case 19:offset=offsetBackForward*34;
		   break;
		case 20:offset=offsetBackForward*36;
		   break;
		default:offset=offsetBackForward*40;
			   break;
		}
		
				
		if(event.isSouth()){  // If the mouse wheel is moved in Up direction the video is brougth forward
			setForwardVideo(offset);			
		}
		else{
			setBackVideo(offset);  // if the mouse wheel is moved in Down direction the video is brought back		
		}
	}
	
	
	
	
	
	
	/**
	 * This metod take in input a int variable offset and brought the video back by the value of offset ms
	 * @param offset : int variable that indicate the amount of ms to brought back the video   
	 * */
	private void setBackVideo(int offset){
		// new video play position
		final double positionVideo;
		
		
		if(videoCanBackForward){  //if video can be bring back. There are no pending changes on the video play position

			bEndPressed=false;			
			videoCanBackForward=false; // Sets that There are pending changes on the video play position.
			mediaPlayer.pauseMedia();  
			positionVideo=mediaPlayer.getPlayPosition() - offset;  // calculate new video position
			
			if(positionVideo > 0)   
				mediaPlayer.setPlayPosition(positionVideo);
			else	// the location of the Video can not be less than zero 
				mediaPlayer.setPlayPosition(0);
			
			setPlayPauseButtonStatus(false);  // the video is in pause so i set the button in pause mode 
			timerProgressBar.run();  // I start the timer that aligns the progressbar to this video
			timerProgressBar.scheduleRepeating(timerRefreshScroolbar + timerRefreshScroolbarOffsetRealignment);
			
			// this timer occurs after that the video is in new Position and controls if there is space for
			// bring the video back
			Timer timerVideoCanBackForward=new Timer() {
				
				@Override
				public void run() {
					//listBoxAddItem("playpos: " + mediaPlayer.getPlayPosition()+ " position: " + positionVideo);
					if(Math.abs((mediaPlayer.getPlayPosition() - positionVideo)) < offsetBackForward){
						videoCanBackForward=true;
						this.cancel();
					} 			
				}
			};
			
			// start the timer that controls if there is space for brought the video back
			timerVideoCanBackForward.scheduleRepeating(timeCinquecentoMs/3);
		}
	}
	
	
	
	
	/**
	 * This metod take in input a int variable offset and brought the video forward by the value of offset ms
	 * @param offset : int variable that indicate the amount of ms to brought forward the video   
	 * */
	private void setForwardVideo(int offset){
    	final double positionVideo;	
    	
    	if(videoCanBackForward){  // if video can be brought forward. There are no pending changes on the video play position
    		videoCanBackForward=false;   // since i'm changing the position of the video, I block further changing to other functions 
    		bEndPressed=false;
    		mediaPlayer.pauseMedia();
    		positionVideo=mediaPlayer.getPlayPosition()+ offset;  // calculate new video position
    		if(positionVideo<durataVideo){  // new position can not be more big than the video size
    			mediaPlayer.setPlayPosition(positionVideo);
    			setPlayPauseButtonStatus(false);					
    			timerProgressBar.run();    // I start the timer that aligns the progressbar to this video
    			timerProgressBar.scheduleRepeating(timerRefreshScroolbar + timerRefreshScroolbarOffsetRealignment);
    			Timer timerVideoCanBackForward=new Timer() {
					
    				// this timer occurs after that the video is in new Position and controls if there is space for
    				// bring the video forward
    				@Override
					public void run() {
						//listBoxAddItem("playpos: " + mediaPlayer.getPlayPosition()+ " position: " + positionVideo);
						if(Math.abs((mediaPlayer.getPlayPosition() - positionVideo)) < offsetBackForward){
							videoCanBackForward=true;
							this.cancel();
						}					
					}
				};
				// start the timer that controls if there is space for brought the video forward
				timerVideoCanBackForward.scheduleRepeating(timeCinquecentoMs/3);
    		}
		}
    }
	

	
	
	/**
	 * 
	 * This method sets the video in pause mode and takes as input a Boolean value that indicates the priority
	 * @param fast: boolean value. If fast is true the method stops the timer immediately without to gives at the progress
	 *  bar the time to align at the video
	 */
	private void pauseVideo(boolean fast){
		videoWasInPlay=false;
		if(fast){   // stop the video immediately
			mediaPlayer.pauseMedia();    // pause the video
			// 
			timerVideoPauseTimeOut.cancel();   
			timerVideoPauseTimeOut.schedule(1);
		}else {
		mediaPlayer.pauseMedia();
		timerVideoPauseTimeOut.schedule(timeTimeOutPause);					
		progressBarVideo.updateText(testoPlayerPause);
		}
	}
		
	
	
	
	/**
	 * This method sets the Progress Bar video position, transforming a X coordinate position in a percentage progress.
	 * The method takes as input two parameters. 
	 * @param xMouse : integer value that represents the x coordinate position to transform in a percentage progress for
	 * the Progress Bar 
	 * @param sliderPBar : boolean value, true if the video is not expected to realign the progress bar, and is typically 
	 * used for frequent changes such as a drag of the cursor of the video in the progress bar
	 */
	private void setProgressBarVideoPosition(int xMouse,boolean sliderPBar){	
		pauseVideo(true);
		final double XmouseTimer=(double) xMouse/ (double) progressBarVideo.getOffsetWidth();
		final double videoPos=XmouseTimer* ((double)mediaPlayer.getMediaDuration());		
		
		
		if(sliderPBar){ // if make a frequent changes in cascade with the drag of cursor on progressBar
			progressBarVideo.updateProgress(XmouseTimer, null);	
			mediaPlayer.setPlayPosition(videoPos);
			annotations.setPlayPosForce(videoPos);
			
		}else {
			// wait the realign of the video to progress Bar
			Timer timerWaitForVideoRealign=new Timer() {
				
				@Override
				public void run() {					
					mediaPlayer.setPlayPosition(videoPos);
					annotations.setPlayPosForce(videoPos);
					progressBarVideo.updateProgress(XmouseTimer, null);					
				}
			};		
			
			timerWaitForVideoRealign.schedule(50); // start the timer that wait the realign of the video to progress Bar
		}
	}
	
	
	
	
	/**
	 * This method sets the Progress Bar and video position, transforming a X coordinate position in a percentage(%) progress
	 * and the corresponding video position of the media player.
	 * @param leftAndPlayPos 
	 */
	private void setProgressBarVideoPosition(NextActiveTag leftAndPlayPos){	
		pauseVideo(true);
		final double XmouseTimer=(double) leftAndPlayPos.getIndexValue()/ (double) progressBarVideo.getOffsetWidth();
		final double videoPos=leftAndPlayPos.getTimeValue();		
		
		// before to make a change i wait that the progress bar is aligned with the mediaplayer video position 
		Timer timerWaitForVideoRealign=new Timer() {
			
				@Override
				public void run() {					
					mediaPlayer.setPlayPosition(videoPos);
					//annotations.setPlayPosForce(videoPos);
					progressBarVideo.updateProgress(XmouseTimer, null);					
				}
			};	
			//start the timer that wait the allignment between video and progress Bar
			timerWaitForVideoRealign.schedule(50);
		
	}
	
	
	
	
	/**
	 * this method is used for open and close the volume slider and show an animation while the slider
	 * is opened or closed  
	 */
	private void sliderAnimate(){
		
		if(sliderVolume.isVisible()){  //if slider is visible than show the close animation 
			sliderVolume.animateHide(AnimationEffect.SLIDE);
			
		}else {	//if slider is not visible than show the open animation 		
			sliderVolume.animateShow(AnimationEffect.SLIDE);			
		}
	}
	
	
	
	
	/**
	 * this metod close the volume slider after timeWait ms
	 * @param timeWait: int value thath rappresent the ms to wait before close the slider
	 */
	private void closeVolumeSlider(int timeWait){
		Timer timersliderVolume=new Timer() {					
			@Override
			public void run() {
				
				// closes only if the slider does not have focus
				if(!sliderVolumeFocused){					
					sliderAnimate();						
					this.cancel();
				}					
			} 
		};
		
		//starts the timer that close slider after timeWait ms
		timersliderVolume.schedule(timeWait);
	}
	
	
	
	
	
	/**
	 * this method put the video media player in end mode
	 */
	private void endMediaPlayer(){
		bEndPressed=true;       // the user press button End
		mediaPlayer.pauseMedia();   // stop the video
		mediaPlayer.setPlayPosition(durataVideo);  // set video play position to the end of the video
		timerProgressBar.cancel();         // stops the no real time next eventual align of progress bar with the video play position and
		timerVideoPauseTimeOut.cancel();   // restart the alignment in real time.	 	
		progressBarVideo.updateProgress(1, "Play End ...");  // set new progress bar caption
		setPlayPauseButtonStatus(false);   // sets the play pause button ready for the play
	}
	
	
	/**
	 * This method sets the PlayPause button status 
	 * @param value: boolean value. if true set the button in play mode otherwise in pause mode
	 */
	private void setPlayPauseButtonStatus(boolean value){
		buttonPlayPause.setDown(value);    
	}
	
	
	/**
	 * This method starts the play of the video media player
	 */
	private void playVideo(){
		progressBarVideo.updateText(testoPlayerPlay);  // sets new progress bar caption
		videoWasInPlay=true;    // set that the video is in play for save the status
		setPlayPauseButtonStatus(true);   // set the play/pause button ready for pause
		timerVideoPauseTimeOut.cancel();  // stops the eventually progress bar alignment after pause													
		timerProgressBar.scheduleRepeating(timerRefreshScroolbar);  // starts the progress bar update timer
		try {
			mediaPlayer.playMedia();  // play the video
		} catch (PlayException e) {
			e.printStackTrace();
		}
		timerProgressBar.run();  // force the first progress bar update 
	}
	
	
	
	/**
	 * This is the main method of a GWT application project and load the GUI of the same application 
	 */
	public void onModuleLoad() {

		valoreVolume=0.5;  // default volume value 50%
		testoPlayerPlay="Playing Video ...";   // progress bar text in play mode
		testoPlayerPause="Pause Video ...";	// progress bar text in pause mode
		videoInPlay="Video/DemoVideo.ogv";  // current play video on media player
		bEndPressed=false;    // the end button are not pressed
		fullScreen=null;      // full screen is at the moment inactive
		dragPBarStart=false;  // drag on progress bar is at the moment inactive
		videoWasInPlay=false; // in this moment the video aren't in play
		mouseIsOverPBar=false; // mouse is out of progress bar area
		videoCanBackForward=true;  // video play position can be changed
		
		
		final RootPanel rootPanel = RootPanel.get();  // gets the browser canvas page
		rootPanel.setSize("100%", "100%"); // set the canvas browser page size
		
		
		canvasPagina=new AbsolutePanel();  // main container of the page
		canvasPagina.setSize("100%", "100%");	// set the page size to 100% of browser space	
		rootPanel.add(canvasPagina, 0, 0);  //add the main container to browser page
		
		// Create the Volume slider
		sliderVolumeFocused=false;		// now slider has no focus
		sliderVolume = new Slider();    
		sliderVolume.setSize("25px", sliderVolumeHeight+"px");		
		sliderVolume.addValueChangedHandler(new ValueChangedHandler() {
			public void onValueChanged(ValueChangedEvent event) {  //on slider volume value change
				mediaPlayer.setVolume(sliderVolume.getValue()/100);  // set new media player volume. slider get value from 0 to 100  while media player set value from 0 to 1
				if(mediaPlayer.getVolume()==0)
					buttonVolume.setDown(true);
				else
					buttonVolume.setDown(false);
				}
		});
		sliderVolume.addMouseOverHandler(new com.smartgwt.client.widgets.events.MouseOverHandler() {
			public void onMouseOver(com.smartgwt.client.widgets.events.MouseOverEvent event) { // on mouse move over slider volume
				sliderVolumeFocused=true;   // slider volume has focus
				}
		});
		sliderVolume.addMouseOutHandler(new com.smartgwt.client.widgets.events.MouseOutHandler() {
			public void onMouseOut(com.smartgwt.client.widgets.events.MouseOutEvent event) { // on mouse exit 
				int xLeft,xRight,yTop,YBottom,XMouse,YMouse;
				
				
				/* In the internal of the slider is displayed a square component that is the cursor of the slider.
				 * When the user click on it for change the volume value, a mouse out event occurs. For this reason, 
				 * before closing the slider when a mouse out event occurs, is therefore opportune to manually check
				 * if the mouse is really out of the slider or within the cursor area.
				 * */
				
				xLeft=sliderVolume.getPageLeft();   // get volume slider x left position
				xRight=xLeft + sliderVolume.getOffsetWidth();    // get volume slider x right position
				yTop=sliderVolume.getPageTop();      // get volume slider y top position
				YBottom=yTop+ sliderVolume.getOffsetHeight();  // get volume slider y bottom position
				XMouse=event.getX();   // get x mouse position
				YMouse=event.getY();   // get y mouse position
				
				
				if(!((XMouse>xLeft) && (XMouse< xRight) && (YMouse > yTop) && (YMouse<YBottom))){	// if the mouse is out of slider area			
					sliderVolumeFocused=false;   // slider lost focus
					sliderAnimate();	// close the slider in animatied mode	
				}
			}
		});		
		sliderVolume.setLabelWidth(15);
		sliderVolume.setValue(50f);     // sets the default volume value to 50%
		sliderVolume.setLength(0);	
		sliderVolume.setUseOpacityFilter(false);
		sliderVolume.setShowTitle(false); // no show title
		sliderVolume.setShowHoverComponents(false);
		sliderVolume.setVertical(true);
		sliderVolume.setStyleName("sliderVolume");
		sliderVolume.setVisible(false);
		sliderVolume.setMinValue(0);
		sliderVolume.setMaxValue(100);
		
		
		
		// Now I want to create internal page 5 areas called respectively the north, east, south, west and finally the center.
		// To do this I start to create a panel divided into three sections of North, Central, South. 
		// Then the inside of the center panel create another panel divided into three sections west, central, east. 
		// At this point I set my container is divided into 5 zones.
		
		// Now I begin to create the main panel North,central,south.
		FlowPanel panelPrincipale = new FlowPanel();
		canvasPagina.add(panelPrincipale, 0, 0);
		panelPrincipale.setSize("100%", "100%");
		
		// North Section
		FlowPanel panelNorth = new FlowPanel();
		panelNorth.setStyleName("nord");
		panelPrincipale.add(panelNorth);
		panelNorth.setSize("100%", "10%");
		
		// Central Section containing West, central, East 
		FlexTable panelCentre = new FlexTable();
		panelCentre.setStyleName("centro");
		panelPrincipale.add(panelCentre);
		panelCentre.setSize("100%", "85%");
		
		// west panel
		VerticalPanel panelWest = new VerticalPanel();
		panelWest.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
		panelWest.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		panelWest.setStyleName("ovest");
		panelCentre.setWidget(0, 0, panelWest);
		panelCentre.getCellFormatter().setHeight(0, 0, "100%");
		panelCentre.getCellFormatter().setWidth(0, 0, "5%");
		panelWest.setSize("100%", "100%");		
		Label labelWest = new Label("West");
		panelWest.add(labelWest);
		
		// central Panel containing video
		FlowPanel panelCentral = new FlowPanel();
		panelCentral.setStyleName("centrale");
		panelCentre.setWidget(0, 1, panelCentral);
		panelCentre.getCellFormatter().setHeight(0, 1, "100%");
		panelCentre.getCellFormatter().setWidth(0, 1, "90%");
		panelCentral.setSize("100%", "100%");
		panelVideoContainer = new AbsolutePanel();
		panelVideoContainer.setStyleName("panelVideoContainer");
		panelCentral.add(panelVideoContainer);		
		panelVideoContainer.setSize("100%", "70%");
		
		//  Now I create the media player
		try {			
			mediaPlayer=new NativePlayer(videoInPlay,true, "100%", "55%");			
			mediaPlayer.addMouseDownHandler(new MouseDownHandler() {
				public void onMouseDown(MouseDownEvent event) { // on mouse click create the annotation and put the video in pause mode
					pauseVideo(false);					
					annotations.addAnnotation(event.getClientX(),event.getClientY(),mediaPlayer.getPlayPosition(),mediaPlayer.getMediaDuration());	
					VideoAnnotationPreview vap=new VideoAnnotationPreview(videoInPlay, mediaPlayer.getPlayPosition()); // crate new preview	obj	
					annotationPrewPanel.addPreview(vap); // add a new annotation preview to preview panel
					vap.addOpenPreviewHandler(new OpenPreviewEventHandler() { // OpenPreviewHandler handler to respond after user click on preview 						
						@Override
						public void onPreviewOpened(OpenPreviewEvent event) {  //On preview Opened/clicked open the video preview on media player 
							mediaPlayer.setPlayPosition(event.getPreviewPlayPosStart()); // open preview on video player	 						
						}
					});
				}
			});
			mediaPlayer.setStyleName("videoPlayer");
			mediaPlayer.setControllerVisible(false); // the default controls of the video should be hidden because hides a small 
			panelVideoContainer.add(mediaPlayer);	//  area of the video and must be customized as external object		
			mediaPlayer.setSize("100%", "100%");
			mediaPlayer.pauseMedia();
			mediaPlayer.setPlayPosition(0);
			mediaPlayer.setLoopCount(1);     // the video don't repeat after the end is reached
			mediaPlayer.setRepeatMode(RepeatMode.REPEAT_OFF);   // sets the playlist mode. Stop playback when end of playlist is reached
			mediaPlayer.setVolume(valoreVolume);  
			mediaPlayer.addDomHandler(new MouseWheelHandler() {				
				@Override
				public void onMouseWheel(MouseWheelEvent event) { // on scroll with the mouse wheel change the time video position
					mouseWhellOnVideo(event);							
				}
			}, MouseWheelEvent.getType());
			
		} catch (LoadException e) {
			Window.alert("Errore Caricamento");
			e.printStackTrace();
		} catch (PluginNotFoundException e) {
			Window.alert("Plugin non Trovato");
			e.printStackTrace();
		}
		
		//create the video controls container
		FlexTable panelVideoControls = new FlexTable();
		panelVideoControls.setStyleName("videoControls");
		panelCentral.add(panelVideoControls);		
		panelVideoControls.setSize("100%", "30%");
		
		//create the progress bar container
		AbsolutePanel panelProgressBar = new AbsolutePanel();
		panelProgressBar.setStyleName("panelProgressBar");
		panelVideoControls.setWidget(0, 0, panelProgressBar);
		panelVideoControls.getCellFormatter().setHeight(0, 0, "15%");
		panelVideoControls.getCellFormatter().setWidth(0, 0, "100%");
		panelProgressBar.setSize("100%", "100%");		
		//create progress bar 
		progressBarVideo = new MyProgressBar();
		progressBarVideo.addMouseOverHandler(new MouseOverHandler() {
			public void onMouseOver(MouseOverEvent event) {
				mouseIsOverPBar=true;
			}
		});
		progressBarVideo.addMouseMoveHandler(new MouseMoveHandler() {
			public void onMouseMove(MouseMoveEvent event) {    // on mouse move over the progress bar, if mouse left button is pressed			
				if(dragPBarStart){							   // move the playpos cursor and consequently the video pos							
					setProgressBarVideoPosition(event.getX(),true);	
				} 
			}
		});
		progressBarVideo.addMouseDownHandler(new MouseDownHandler() {
			public void onMouseDown(MouseDownEvent event) {  // on mouse down move the playpos cursor and consequently the video pos	
				videoWasInPlay=buttonPlayPause.isDown();
				dragPBarStart=true;			
				videoCanBackForward=true;
				setProgressBarVideoPosition(event.getX(),false);				
			}
		});
		progressBarVideo.addMouseUpHandler(new MouseUpHandler() {
			public void onMouseUp(MouseUpEvent event) {  // on mouse up stop the drag of video position and allign the player with progress bar
				dragPBarStart=false;
				// timer to wait the realignment betwen video player and progress bar
				Timer timeRiavviaVideoPBar=new Timer() {					
					@Override
					public void run() {
						// when the timer event occurs, before to put the video in play mode, it's needed to check if the
						// user in the time betwen the drag end and now, not have begin a new drag action on progress bar
						if(!dragPBarStart)
							playVideo();
						}
				};				
				if(videoWasInPlay)    // if video was in play, start the timer that control the progress bar allignment with the video
					timeRiavviaVideoPBar.schedule(timeCinquecentoMs);  
			}
		});
		progressBarVideo.addMouseOutHandler(new MouseOutHandler() {
			public void onMouseOut(MouseOutEvent event) {   // on mouse out 
				mouseIsOverPBar=false;
			
				/*
				 * While the user drag on progress bar, the mouse cursor can exit by the progress bar area so
				 * to sure if the mouse is exited volontary when the drag is ended or if the mouse is exited involontary,
				 * is necesary to wait some time, before considering the drag concluded and set that the mouse is outside 
				 * of the progress bar area
				 * */
				Timer timerDisattivaDrag=new Timer() {					
					@Override
					public void run() {
						if(!mouseIsOverPBar)     // if mouse is out after some time, the drag can be considered concluded
							dragPBarStart=false;						
					}
				};				
				
				// if drag in progress bar was in running, start the timer that stop the drag controls of the progress bar
				if(dragPBarStart)
					timerDisattivaDrag.schedule(timeCinquecentoMs);
			}
		});
		
		progressBarVideo.updateProgress((float) 0.5, "Video Player Bar ...");
		panelProgressBar.add(progressBarVideo);
		progressBarVideo.setHeight("");
		
		// create the anotation bar where to show the annotations links
		panelAnnotationBar=new AbsolutePanel();
		panelAnnotationBar.setStyleName("AnnotationBar");				
		panelVideoControls.getCellFormatter().setHeight(1, 0, "50%");
		panelVideoControls.getCellFormatter().setWidth(1, 0, "100%");
		panelAnnotationBar.setSize("100%", "100%");		
		annotationBar = new Canvas();
		annotationBar.setBackgroundRepeat(BkgndRepeat.REPEAT);  //set background image mode on Repeat
		annotationBar.setSize("870px", "89px");
		annotationBar.setBackgroundColor("White");
		annotationBar.setOverflow(Overflow.CLIP_H);		
		annotationBar.setBackgroundImage("/Img/Icons/TagBar/tagbkgndblue.png");   // background image as grid
		/*
		 *  the annotation bar can contain more links in the same column so is necessary insert the
		 *  annotation Bar in a scroolPanel for scrolling the links.
		 */
		scrollPanel=new ScrollPanel(annotationBar);    
		panelAnnotationBar.add(scrollPanel,0,0);
		scrollPanel.setSize("870px", "90px");
		panelVideoControls.setWidget(1, 0, panelAnnotationBar);
		
		// create the video controls container divided in 3 section, West, Central, East
		FlexTable panelControls = new FlexTable();
		panelControls.setStyleName("panelControls");
		panelVideoControls.setWidget(2, 0, panelControls);
		panelVideoControls.getCellFormatter().setHeight(2, 0, "35%");
		panelVideoControls.getCellFormatter().setWidth(2, 0, "100%");
		panelControls.setSize("100%", "100%");
		
		// west panel of controls container
		SimplePanel panelWestControls = new SimplePanel();
		panelControls.setWidget(0, 0, panelWestControls);
		panelWestControls.setSize("100%", "100%");
		panelControls.getCellFormatter().setHeight(0, 0, "100%");
		panelControls.getCellFormatter().setWidth(0, 0, "40%");
		panelControls.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER);
		
		//central panel of controls container
		final HorizontalPanel panelCentralControls = new HorizontalPanel();
		panelControls.setWidget(0, 1, panelCentralControls);
		panelControls.getCellFormatter().setHeight(0, 1, "100%");
		panelControls.getCellFormatter().setWidth(0, 1, "20%");
		panelCentralControls.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		panelCentralControls.setSize("100%", "100%");
		
	
		//****************************************************
		//*       		BUTTON STOP VIDEO
		//****************************************************
		/*
		 * the goal of stop button is stops the play video and set the 
		 * video play position to the begin
		 * */
		final Button buttonStop = new Button("New button");
		panelCentralControls.add(buttonStop);
		buttonStop.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				bEndPressed=false;   // set button end not pressed
				timerVideoPauseTimeOut.cancel();  // stops progress bar update after pause
				timerProgressBar.cancel();	 // stops progress bar update
				mediaPlayer.stopMedia();   // stop media player
				mediaPlayer.pauseMedia();  // pause media player
				setPlayPauseButtonStatus(false); // set play/pause button redy for play					
				progressBarVideo.updateProgress((float) 0, testoPlayerPause);  // update progress bar 
				annotations.setPlayPosForce(0);	// update annotation visible tags						
			}
		});
		buttonStop.setStyleName("stopButton");
		buttonStop.setText("");
		buttonStop.setSize("35px", "35px");
		
		
		
		//****************************************************
		//*       			BUTTON BACK VIDEO
		//****************************************************
		/*
		 * The Goal of button back is set the video back by offsetBackForward frame
		 * */
		Button buttonBack = new Button("New button");
		panelCentralControls.add(buttonBack);
		buttonBack.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				setBackVideo(offsetBackForward);  // sets the video Back by offsetBackForward frame				
			}
		});
		buttonBack.setStyleName("backButton");
		buttonBack.setText("");
		buttonBack.setSize("35px", "35px");
		
		
		
		//****************************************************
		//*       			BUTTON PLAY PAUSE
		//****************************************************
		/*
		 * The goal of play/pause button is to set the video in play or in pause mode
		 * if the video is in play set the video in pause, otherwise set the video in play 
		 * */
		AbsolutePanel panelPlayPause = new AbsolutePanel();
		panelCentralControls.add(panelPlayPause);
		panelPlayPause.setSize("35px", "35px");
		
		buttonPlayPause = new ToggleButton("Up text");
		buttonPlayPause.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				
				if(!buttonPlayPause.isDown()){   // put the video in pause mode
					videoWasInPlay=false;  // save the video status as in pause
					pauseVideo(false); //pause video takes in input a boolean value. if false pauseVideo() method realign video and progress bar
				}else {                
					/*
					 * if buttonEnd is pressed is necessary to wait a few ms before to play the video because after the endVideo
					 * functionally the video player requires several milliseconds before returning the video to the begin position 
					 * and be ready to play again
					 * */
					if(bEndPressed){  
							buttonStop.click();		 
							Timer timerRiavviaVideoDopoEnd=new Timer() {							
								@Override
								public void run() {
									if(mediaPlayer.getPlayPosition()==0){
										this.cancel();										
										playVideo();	
										panelCentralControls.setVisible(true);										
						 			}									
								}
						 	};	
						 	timerRiavviaVideoDopoEnd.scheduleRepeating(50); // start the timer that wait 50ms before to paly the video again
						 	panelCentralControls.setVisible(false);
					} else playVideo();
				}						
			   bEndPressed=false;
			}
		});
		panelPlayPause.add(buttonPlayPause);
		buttonPlayPause.setSize("35px", "35px");
		buttonPlayPause.setDown(true);
		buttonPlayPause.setStyleName("playPauseButton");
		Image image = new Image("Img/Icons/Player/Pause.png");
		buttonPlayPause.getDownFace().setImage(image);
		buttonPlayPause.getUpFace().setImage(new Image("Img/Icons/Player/Play.png"));
		   
		
		
		//****************************************************
		//*       			BUTTON FORWARD VIDEO
		//****************************************************	
		/*
		 * The Goal of button forward is set the video forward by offsetBackForward frame
		 * */
		Button buttonForward = new Button("New button");
		panelCentralControls.add(buttonForward);
		buttonForward.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) { //on button click
				setForwardVideo(offsetBackForward);  // sets the video forward by offsetBackForward * mouseWhell rotation					
			}
		});
		buttonForward.setStyleName("forwardButton");
		buttonForward.setText("");
		buttonForward.setSize("35px", "35px");
		

	
		//****************************************************
		//*       			BUTTON END PLAY VIDEO
		//****************************************************	
		/*
		 * the goal of End button is stops the play video and set the 
		 * video play position to the end
		 * */
		final Button buttonEnd = new Button("New button");
		panelCentralControls.add(buttonEnd);
		buttonEnd.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
					endMediaPlayer();					
					bEndPressed=true;				
					
					/*
					 * To correct a little imperfection of the player that in many cases when the video play is almost at the end time 
					 * and a user apply the function end, aging stop the video at the end, starts again it from the beginning, 
					 * is necessary repeat the end video operation after a few milliseconds so that if the video is restarted, now 
					 * it is at the start time, therefore applying the function end we are sure that it will be made in end position
					 * */
					Timer timerStopAfterEnd=new Timer() {						
						@Override
						public void run() {
							this.cancel();
							if(mediaPlayer.getPlayPosition()<durataVideo){
								endMediaPlayer();	
							}							
						}
					};					
					timerStopAfterEnd.scheduleRepeating(300);  // start the timer 300 ms after the first end call  
				}				
			});
		buttonEnd.setStyleName("endButton");
		buttonEnd.setText("");
		buttonEnd.setSize("35px", "35px");
		
		
		
		//****************************************************
		//*       			BUTTON VOLUME
		//****************************************************
		/*
		 * The Goal of button volume is to set the media player volume
		 * */
		buttonVolume = new ToggleButton("");
		buttonVolume.addMouseOutHandler(new MouseOutHandler() {
			public void onMouseOut(MouseOutEvent event) {
				closeVolumeSlider(timeTimeOutCloseSlideBar);
			}
		});
		buttonVolume.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if(buttonVolume.isDown()){   // begin of volume setting, so now read the volume value from the media player
					valoreVolume=mediaPlayer.getVolume();
					mediaPlayer.setVolume(0);					
				}else {     // end of volume setting, so now write the volume value to the media player
					mediaPlayer.setVolume(valoreVolume);
				}
			}
		});
		buttonVolume.getDownFace().setImage(new Image("Img/Icons/Player/VolumeDisabled.png"));		
		buttonVolume.addMouseOverHandler(new MouseOverHandler() {
			public void onMouseOver(MouseOverEvent event) { //if not visible open the volume slider controls
				if(!sliderVolume.isVisible()){											
					sliderVolume.setValue((int) (mediaPlayer.getVolume()*100));		
					sliderAnimate();
					}
			}
		});
		buttonVolume.setStyleName("VolumeButton");						
		buttonVolume.getUpFace().setImage(new Image("Img/Icons/Player/Volume.png"));
		panelCentralControls.add(buttonVolume);
		buttonVolume.setSize("35", "35");
		
		
		//****************************************************
		//*       			BUTTON FULL SCREEN
		//****************************************************	
		/*
		 * The Goal of this button is to open the video in full screen mode
		 * */
	 	Button buttonFullScreen = new Button("");	
	 	buttonFullScreen.addClickHandler(new ClickHandler() {
	 		public void onClick(ClickEvent event) {  // on click open the full screen video custom window
	 			int screenWidth,screemHeight;
	 			mediaPlayer.pauseMedia();
	 			screenWidth=canvasPagina.getOffsetWidth();
	 			screemHeight=canvasPagina.getOffsetHeight();
	 				
	 			fullScreen=new PlayerFullScreen(videoInPlay,mediaPlayer.getPlayPosition(),screenWidth, screemHeight);	 	
	 			fullScreen.addFullScreenCloseHandler(new FullScreenEventHandler() {
	 				
	 				/*
	 				 * On custom full screen window close, set the focus at the video in the browser page. If the
	 				 * video was in play in full screen window than the video in the browser page must be made in play. 
	 				 * The video should inherit the status it had in full screen mode.
	 				 * */
	 				@Override
					public void onCloseFullScreen(FullScreenEvent event,double posVideo,boolean videoPlayin) {
						fullScreen=null;
						mediaPlayer.setPlayPosition(posVideo);		
						if(videoPlayin)
							try {
								mediaPlayer.playMedia();
							} catch (PlayException e) {
								e.printStackTrace();
							}
						else mediaPlayer.pauseMedia();								
					}
				});	 			 
	 		}
	 	});
		buttonFullScreen.setStyleName("FullScreenButton");
		panelCentralControls.add(buttonFullScreen);
		buttonFullScreen.setSize("35px", "35px");
		
		
		// Panel East of video control conatiner. Control Container consists of three panel container (West,Central,East) 
		SimplePanel panelEastControls = new SimplePanel();
		panelControls.setWidget(0, 2, panelEastControls);
		panelEastControls.setSize("100%", "100%");
		panelControls.getCellFormatter().setHeight(0, 2, "100%");
		panelControls.getCellFormatter().setWidth(0, 2, "40%");
		panelControls.getCellFormatter().setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_CENTER);
		panelControls.getCellFormatter().setVerticalAlignment(0, 1, HasVerticalAlignment.ALIGN_TOP);
		panelControls.getCellFormatter().setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
		panelControls.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_TOP);
		panelControls.getCellFormatter().setVerticalAlignment(0, 2, HasVerticalAlignment.ALIGN_TOP);
		panelVideoControls.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_TOP);
		panelVideoControls.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER);
		panelVideoControls.getCellFormatter().setVerticalAlignment(2, 0, HasVerticalAlignment.ALIGN_TOP);
		panelVideoControls.getCellFormatter().setHorizontalAlignment(2, 0, HasHorizontalAlignment.ALIGN_CENTER);
				
		
		
		// Panel East on browser page of @SaStria application
		VerticalPanel panelEast = new VerticalPanel();
		panelEast.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
		panelEast.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		panelEast.setStyleName("est");
		panelCentre.setWidget(0, 2, panelEast);
		panelEast.setSize("100%", "100%");
		Label labelEast = new Label("East");
		panelEast.add(labelEast);
		
		
		
		// Annotation preview panel drawn after the video is loaded in the timer function 
		/*
		int pvcl=panelVideoContainer.getOffsetWidth() + panelVideoContainer.getAbsoluteLeft();
		int videol=annotationBar.getPageLeft()+annotationBar.getWidth();		
		annotationPrewPanel = new AnnotationPreviewPanel(videol,panelVideoContainer.getAbsoluteTop(),pvcl-videol,panelVideoContainer.getOffsetHeight());
		panelEast.add(annotationPrewPanel);
		*/
		
		panelCentre.getCellFormatter().setHeight(0, 2, "100%");
		panelCentre.getCellFormatter().setWidth(0, 2, "5%");
		panelCentre.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER);
		panelCentre.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_MIDDLE);
		panelCentre.getCellFormatter().setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
		panelCentre.getCellFormatter().setVerticalAlignment(0, 1, HasVerticalAlignment.ALIGN_MIDDLE);
		panelCentre.getCellFormatter().setVerticalAlignment(0, 2, HasVerticalAlignment.ALIGN_MIDDLE);
		panelCentre.getCellFormatter().setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_CENTER);
		
		
		
		// Panel South on browser page of @SaStria application
		FlowPanel panelSouth = new FlowPanel();
		panelSouth.setStyleName("sud");
		panelPrincipale.add(panelSouth);
		panelSouth.setSize("100%", "5%");		
		VerticalPanel panelTitoloCoda = new VerticalPanel();
		panelTitoloCoda.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
		panelTitoloCoda.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		panelSouth.add(panelTitoloCoda);
		panelTitoloCoda.setSize("100%", "100%");		
		Label labelTitoloCoda = new Label("Laboratorio Contenuti / Laboratorio Tv Collaborativa");
		panelTitoloCoda.add(labelTitoloCoda);
			
		// Panel North container. it contain panelNorthContainer, panelNorthCentral, panelNorthSouth
		FlexTable panelNorthContainer = new FlexTable();
		panelNorth.add(panelNorthContainer);
		panelNorthContainer.setSize("100%", "100%");
				
		// Panel North left. it contains @SaStria logo
		AbsolutePanel panelNorthLeft = new AbsolutePanel();
		panelNorthContainer.setWidget(0, 0, panelNorthLeft);
		panelNorthContainer.getCellFormatter().setHeight(0, 0, "100%");
		panelNorthContainer.getCellFormatter().setWidth(0, 0, "20%");
		panelNorthLeft.setSize("100%", "100%");
			
		// @SaStria logo downloaded by "http://www.artedelricamo.com/" and modified
		Image labelSaStriaLogo = new Image("Img/Icons/logo/SaStria.png");
		panelNorthLeft.add(labelSaStriaLogo, 0, 0);
		labelSaStriaLogo.setSize("50%", "100%");
				
		// Panel North Central. it contains @SaStria video Url Text
		FlowPanel panelNorthCentral = new FlowPanel();
		panelNorthContainer.setWidget(0, 1, panelNorthCentral);
		panelNorthContainer.getCellFormatter().setHeight(0, 1, "100%");
		panelNorthContainer.getCellFormatter().setWidth(0, 1, "60%");
		panelNorthCentral.setSize("100%", "100%");
		Label labelTitolo = new Label("Sa Stria Project Clone");
		panelNorthCentral.add(labelTitolo);
				
				
				
				
		/***********************************************
		 * 
		 * DEBUG PRINTING BUTTON
		 * 
		 ********************************************** */
		final Button button = new Button("New button");
		panelNorthCentral.add(button);
		button.addClickHandler(new ClickHandler() {
		public void onClick(ClickEvent event) {
			
		//Window.alert(cloudTagLinksPanel.getWidth() + " " + cloudTagLinksPanel.getHeight());	
				//panelSlider.
				//annotations.print();
		
		}
		});
		button.setWidth("95px");
		
		// Url Box Text writer where the user write the url of the video to load for the annotations tool
		HorizontalPanel horizontalPanel = new HorizontalPanel();
		panelNorthCentral.add(horizontalPanel);
		Label lblUrlVideo = new Label("Url Video:  ");
		horizontalPanel.add(lblUrlVideo);
		lblUrlVideo.setSize("66px", "100%");		
		TextBox textBoxUrl = new TextBox();
		textBoxUrl.setText("Video/DemoVideo.ogv"); // Default URL of the video
		horizontalPanel.add(textBoxUrl);
		textBoxUrl.setSize("299px", "100%");
			
		
		//// Panel North Right. Now it contains nothing.
		AbsolutePanel panelNorthRight = new AbsolutePanel();
		panelNorthContainer.setWidget(0, 2, panelNorthRight);
		panelNorthContainer.getCellFormatter().setHeight(0, 2, "100%");
		panelNorthContainer.getCellFormatter().setWidth(0, 2, "20%");
		panelNorthRight.setSize("100%", "100%");
		panelNorthContainer.getCellFormatter().setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
		panelNorthContainer.getCellFormatter().setVerticalAlignment(0, 1, HasVerticalAlignment.ALIGN_MIDDLE);
		panelNorthContainer.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER);
		panelNorthContainer.getCellFormatter().setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_CENTER);
		panelNorthContainer.getCellFormatter().setVerticalAlignment(0, 2, HasVerticalAlignment.ALIGN_MIDDLE);
		panelNorthContainer.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_MIDDLE);
		
		// add a slider volume Box as invisible to the browser page. Since this component is invisible at the moment, it must be loaded as 
		// the last component on the page for prevent overlap problem with other components when becomes visible. 
		canvasPagina.add(sliderVolume, buttonVolume.getAbsoluteLeft() - 5 , buttonVolume.getAbsoluteTop() - sliderVolumeHeight - 5 );

		
		/*		 
		 * This timer is executed after some ms(allignment time) that the user puts the video in pause mode. This allows the alignment 
		 * and synchronization between video play position and progress bar because in this alignment time the progress bar is continuously
		 * updated while the video is stopped, Therefore synchronization is assured. 
		 * */
		timerVideoPauseTimeOut= new Timer() {			
			@Override
			public void run() {				
				timerProgressBar.cancel();  //stops the timerProgressBar that controls the progress bar update
				progressBarVideo.updateText(testoPlayerPause);
				setPlayPauseButtonStatus(false);
				bEndPressed=false;								
			}
		};
		
		
		/*
		 * The Goal of this timer is update the progressBar for align it to the video play position and open
		 * the annotations according to video play position.
		 * While the video is in play this timer is executed every few ms and the progress bar is updated
		 * according to the video play position as well as the management and the opening of annotations. 
		 * 
		 * */
		timerProgressBar=new Timer() {			
			@Override
			public void run() {							
				double videoPosition=mediaPlayer.getPlayPosition();	  //get the video position		
				progressBarVideo.updateProgress((float) (videoPosition/durataVideo), null);  // set progress bar video position
				annotations.setPlayPosRun(videoPosition); // open annotations that fall within the time in question
				if((videoPosition>=durataVideo) &&(!bEndPressed)){  //if the end of video is reached then the video play should be stopped
					buttonStop.click();						
				}
			}						
		};

		
		/*
		 * This timer is executed after the begining of video loading and the goal of this timer is control continuously
		 * if the video loading is accetable for begin the play of the video. When the minimum video loadin for play video
		 * is reached the media player is initialized, the video is put into play, and the timer for progress bar update is
		 * initialized and executed.  
		 */
		Timer timerVideoLoaded=new Timer() {
			
			@Override
			public void run() {
				durataVideo=mediaPlayer.getMediaDuration();   //get video duration
				if(durataVideo>0){  // if videoduration greater than zero, the video minimum video loadin is reached. 
					this.cancel(); //stop this timer because the video minimum loading i reached and the video can be put into play.		
					
					// Set Progress Bar e Annotation bar size and position according to video player size e spazial coordinate position
					progressBarVideo.setPosition(mediaPlayer.getAbsoluteLeft(), progressBarVideo.getAbsoluteTop());
					progressBarVideo.setWidth(mediaPlayer.getOffsetWidth());					
					annotationBar.setWidth(mediaPlayer.getOffsetWidth());
					panelAnnotationBar.setWidgetPosition(scrollPanel,progressBarVideo.getAbsoluteLeft()-panelAnnotationBar.getAbsoluteLeft(),0);
					scrollPanel.setSize(mediaPlayer.getOffsetWidth()+"px", panelAnnotationBar.getOffsetHeight()+"px");
					annotationBar.setPageLeft(scrollPanel.getAbsoluteLeft());
					annotationBar.setMaxWidth(scrollPanel.getOffsetWidth());
					annotationBar.setHeight(scrollPanel.getOffsetHeight());					
					scrollPanel.setWidth(scrollPanel.getOffsetWidth()+16+"px");
					
					// Annotation preview panel 
					int pvcl=panelVideoContainer.getOffsetWidth() + panelVideoContainer.getAbsoluteLeft();
					int videol=annotationBar.getPageLeft()+annotationBar.getWidth();		
					annotationPrewPanel = new AnnotationPreviewPanel(videol,panelVideoContainer.getAbsoluteTop(),pvcl-videol,panelVideoContainer.getOffsetHeight());
					annotationPrewPanel.draw();
					
					// Cloud tag links panel									
					 
					pvcl=mediaPlayer.getAbsoluteLeft()-panelVideoContainer.getAbsoluteLeft();
					cloudTagLinksPanel=new CloudTagLinks(panelVideoContainer.getAbsoluteLeft(),panelVideoContainer.getAbsoluteTop(), pvcl, panelVideoContainer.getOffsetHeight());
					cloudTagLinksPanel.draw();
					
					// Sets the video in play mode for playin the video and starts the progressbar timer update.
					try {						
						mediaPlayer.playMedia();						
						videoWasInPlay=true;
						progressBarVideo.updateText(testoPlayerPlay);						
						timerProgressBar.scheduleRepeating(timerRefreshScroolbar);
						timerProgressBar.run();										
					} catch (PlayException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
										
				}
							
			}
		};
		
		timerVideoLoaded.scheduleRepeating(timeCinquecentoMs);   // starts the timer that runs every timeCinquecentoMs to check that the minimum video loading is reached
		annotations=new AnnotationAdministrator(annotationBar,mediaPlayer); // create the Annotation administrator object
		annotations.addAnnotationMovedHandler(new SaStriaCustomEventHandler() {
			
			/*
			 * On Annotation moved, the play position of video needs to be updated.
			 * */
			@Override
			public void onAnnotationMoved(SaStriaCustomEvent event,	NextActiveTag newLeftPosition) {
				videoWasInPlay=buttonPlayPause.isDown(); // save the status of video play status	   				
				videoCanBackForward=true;	// the video can be moved back and forward			
				setProgressBarVideoPosition(newLeftPosition);	// sets new video play position according to moved annotation position		
				annotationPrewPanel.updateAnnotationPreviewTimeSegment(event.getAnnotationPreviewIndex(), event.getTimeStart(), event.getTimeEnd());
			}
		});
		
		
		/*
		 * On Annotation saved, the annotation preview video start and end segment must be updated.
		 * */
		annotations.addAnnotationSaveHandler(new AnnotationSaveEventHandler() {
			
			@Override
			public void onAnnotationSaved(AnnotationSaveEvent event) {
				annotationPrewPanel.updateAnnotationPreviewTimeSegment(event.getAnnotationPreviewIndex(), event.getTimeStart(), event.getTimeEnd());
				
			}
		});
		
		/*
		 * On Annotation key Word is set, the cloud tag links must be updated
		 */
		annotations.addAnnotationKeyWordBlur(new AnnotationKeywordBlurEventHandler() {
			
			@Override
			public void onAnnotationKeyWordBlur(AnnotationKeywordBlurEvent event) {
				//Window.alert(event.getKeyWordAnnotationValue());	
				if(event.getIfIsNewInsertedValue())
					cloudTagLinksPanel.addKeyWord(event.getKeyWordAnnotationValue());
				else
					cloudTagLinksPanel.changeKeyWord(event.getOldKeyWordAnnotationValue(), event.getKeyWordAnnotationValue());
							
			}
		});
		
		
		/*
		 * On Annotation description change, the annotation preview label must be updated.
		 * */
		annotations.addAnnotationDescrTextChange(new AnnotationDescrTextChangeEventHandler() {
			
			@Override
			public void onKeyWordTextChange(AnnotationDescrTextChangeEvent event) {
				annotationPrewPanel.updatePreviewTextDescription(event.getAnnotationPreviewText(), event.getAnnotationPreviewIndex());				
			}
		});
		
	}
}


